package cfdt.ldl.web.interceptor;

import cfdt.common.vo.ObjectBaseResponse;
import cfdt.common.exception.CodeException;
import cfdt.ldl.core.system.SystemConstants;
import cfdt.tools.json.JsonUtil;
import cfdt.ldl.web.util.WebTokenUtil;
import cfdt.ldl.web.helper.TokenSessionHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import org.springframework.http.HttpHeaders;
import static cfdt.common.constants.DefaultConstants.HTTP_STATUS_AUTH;


/**
 * <pre>
 * Modify Information:Token拦截器（拦截请求校验token）
 * Author       Date          Description
 * ============ ============= ============================
 * chenzhibin      2021年1月22日    create this file
 * </pre>
 */
@Component
public class TokenInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger("TokenInterceptor");

    @Autowired
    private TokenSessionHelper tokenSessionHelper;

    // 在业务处理器处理请求之前被调用
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String url = request.getRequestURI();
        logger.info("TokenInterceptor拦截请求url:" + url);

        String token = request.getHeader(HttpHeaders.AUTHORIZATION);
        String userId;
        Map<String, Object> redisValMap;
        try {
            // 获取用户ID
            userId = WebTokenUtil.getUserId(token, SystemConstants.secret);
            // 获取redis的用户信息
            redisValMap = tokenSessionHelper.getRedisValMap(request, SystemConstants.secret);
            // 校验token
            WebTokenUtil.validateToken(token, redisValMap, SystemConstants.secret);
        } catch (CodeException ce) {
            logger.error("{}token验证失败{} token: {}", url, ce.getMessage(), token);
            // 处理失败场景HTTP响应
            onFail(response, ce);
            return false;
        }

        // 刷新Token的缓存
        tokenSessionHelper.refreshTokenSession(userId);
        return true;
    }


    // 在业务处理器处理请求完成之后，生成视图之前执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // Do nothing

    }

    // 在DispatcherServlet完全处理完请求之后被调用，可用于清理资源
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // Do nothing

    }

    /**
     * 拦截器失败时的操作
     */
    private void onFail(HttpServletResponse response, CodeException codeException) throws IOException {
        response.setStatus(HTTP_STATUS_AUTH);
        response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);

        ObjectBaseResponse baseResponse = ObjectBaseResponse.error(codeException);
        response.getWriter().write(JsonUtil.toJsonStr(baseResponse));
    }


}
